﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Text.RegularExpressions;
using System.Threading;
using A2DFramework.HttpLoadBalancer.Utility;
using A2DFramework.HttpLoadBalancer.HttpProtocal;
using A2DFramework.HttpLoadBalancer.Parsers;
using A2DFramework.HttpLoadBalancer.Parsers.ConcreteParsers;

namespace A2DFramework.HttpLoadBalancer.Connection
{
    public class ContentServerForwarder
    {
        private Uri uri;
        private HttpRequestEntity requestInfo;

        public ContentServerForwarder(string url, HttpRequestEntity request)
        {
            this.uri = new Uri(url);
            this.requestInfo = request;
        }

        internal HttpResponseEntity GetResponse()
        {
            string sHeaders = string.Empty;
            string strResult = string.Empty;

            byte[] bodyBytes=null;

            using (Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
            {
                requestInfo.HttpHeaders.SetHeader("Host", this.uri.Host);

                StringBuilder buf = new StringBuilder();

                buf.AppendFormat("{0} {1} {2}{3}", Helper.ConvertHttpAction(requestInfo.RequestLine.Action),
                                                   requestInfo.RequestLine.Path,
                                                   Helper.ConvertHttpVersion(requestInfo.RequestLine.Version),
                                                   Consts.CRLF);

                buf.Append(Helper.ConvertHttpHeaders(requestInfo.HttpHeaders));
                buf.Append(Consts.CRLF);

                socket.Connect(this.uri.Host, 80);

                List<byte> data = new List<byte>();
                byte[] ms = System.Text.UTF8Encoding.UTF8.GetBytes(buf.ToString());
                data.AddRange(ms);

                if (requestInfo.RequestLine.Action == HttpRequestActions.POST)
                {
                    if (this.requestInfo.BodyBytes != null)
                        data.AddRange(this.requestInfo.BodyBytes);
                }
                socket.Send(data.ToArray());
                

                Console.WriteLine("1111111");


                byte[] firstData;
                int retryCount = 0;
            receiveBuffer:
                firstData = SocketHelper.ReadRequestBytes(socket, SocketHelper.maxBufferBytes);
            if (firstData == null)
            {
                retryCount++;
                Thread.Sleep(300);
                if (retryCount > 50)
                {
                    Console.WriteLine("超出50次重试");
                    return null;
                }
                goto receiveBuffer;
            }
                strResult = System.Text.Encoding.UTF8.GetString(firstData);

                Console.WriteLine("2222222222");

                if (requestInfo.RequestLine.Action == HttpRequestActions.GET
                    || requestInfo.RequestLine.Action == HttpRequestActions.POST
                    || requestInfo.RequestLine.Action == HttpRequestActions.PUT)
                {
                    Console.WriteLine("33333333");

                    HttpResponseEntity tmpResponse = Parsers.Parsers.HttpResponseParser.Parse(strResult);
                    if (tmpResponse.HttpHeaders.ContentLength != null && tmpResponse.HttpHeaders.ContentLength.HasValue)
                    {
                        int contentLength = int.Parse(tmpResponse.HttpHeaders.ContentLength.Value.Value);

                        List<byte> chunk = new List<byte>();
                        chunk = Helper.GetHttpBodyBytes(firstData, null).ToList();

                        while (chunk.Count < contentLength)
                        {
                            byte[] deepData = SocketHelper.ReadRequestBytes(socket, SocketHelper.maxBufferBytes);
                            if (deepData!=null)
                                chunk.AddRange(deepData);
                            Console.WriteLine(string.Format("data.Count < contentLength====>{0} vs {1}", chunk.Count, contentLength));
                        }
                        bodyBytes = chunk.ToArray();
                    }
                    else
                    {
                        byte[] deepData = SocketHelper.ReadRequestBytes(socket, SocketHelper.maxBufferBytes);
                        Console.WriteLine("44444444");
                        bodyBytes = Helper.GetHttpBodyBytes(firstData, deepData);
                        Console.WriteLine("555555555");
                    }
                }
                Console.WriteLine("66666666");
                socket.Close();
            }
            Console.WriteLine("77777777");
            HttpResponseEntity backendServerResponse = Parsers.Parsers.HttpResponseParser.Parse(strResult);
            Console.WriteLine("88888888");
            backendServerResponse.BodyBytes = bodyBytes;
            return backendServerResponse;
        }
    }
}
